/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package khmhappointmentsystem;

import java.net.InetAddress;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author mbelisle
 */
public class User {

    private static int loginCount = 0;
    private static String userName = "";
    private static String userGroup = "";
    private static int timeout = 0;
    private static String permissions = "";
    static final Logger logger = Logger.getLogger(User.class.getName());
    public static final String administratorString = "File-true|Log Out-true|Change Password-true|Patient-true|Register Patient-true|Patient History-true|Appointment-true|Schedule Appointment-true|Current Appointments-true|Close Appointment-true|Clinics-true|Create New Clinic-true|Edit Clinic-true|Physiotherapy-true|Appointments-true|Productivity Report|Reports-true|Specialist Clinic Tally Checkin-true|Clinic Listing-true|Permissions-true|Create New User-true|Update User-true|Help-true|About-true|";
    public static final String staffString = "File-true|Log Out-true|Change Password-true|Patient-true|Register Patient-true|Patient History-true|Appointment-true|Schedule Appointment-true|Current Appointments-true|Close Appointment-true|Clinics-true|Create New Clinic-true|Edit Clinic-true|Reports-true|Specialist Clinic Tally Checkin-true|Clinic Listing-true|Help-true|About-true|";

    /**
     * This function checks to see if the given username and password matches
     * one stored in the database.
     * @param username
     * @param password
     * @return True of the username is found and the passwords match,
     *         False if it wasn't found or the passwords don't match.
     */
    public static boolean logIn(String username, String password) {
        String storedPassword = "";
        String encryptedPassword = EncryptionHandler.encryptPassword(password);
        boolean successful = false;
        try {
            String sql = "SELECT username, pword, userStatus, userGroup, permission FROM Permissions   WHERE username = ? AND userStatus = 'Active'";
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            prep.setString(1, username);
            ResultSet rs = prep.executeQuery();
            while (rs.next()) {
                storedPassword = rs.getString("pword");
                userName = username;
                userGroup = rs.getString("userGroup");
                permissions = rs.getString("permission");
            }
            rs.close();
            prep.close();
            if (storedPassword.equals(encryptedPassword)) {
                successful = true;
                //Log the action
                String computername = InetAddress.getLocalHost().getHostName();
                String IP = InetAddress.getLocalHost().getHostAddress();
                String message = "SUCCESS: The user successfully logged on from " + IP + ".";
                iLogger.logMessage(message, "Log On", "User");
            } else {
                String computername = InetAddress.getLocalHost().getHostName();
                String IP = InetAddress.getLocalHost().getHostAddress();
                String message = "ERROR: Failed to login as " + username + " from " + IP + ".";
                iLogger.logMessage(message, "Log On", "User");
                loginCount++;
                successful = false;
            }
        } catch (Exception e) {
            String message = "ERROR: Could not validate user information.";
            logger.log(Level.SEVERE, message, e);
            message = "An error occurred while validating the login information.\n"
                    + "Kindly consult your system administrator.";
            Utilities.showErrorMessage(null, message);
        }
        if (loginCount >= 3) {
            String message = "You have exceeded the number of failed login attempts.\n"
                    + "The program will now exit.";
            Utilities.showErrorMessage(null, message);
            khmhappointmentsystem.Main.getApplication().exit();
        }
        return successful;
    }

    /**
     * This function adds a user to the system.
     * @param username
     * @param password
     * @param firstName
     * @param lastName
     * @param group
     * @returns True if the user was added to the system.
     *          Will return false if the username already exists.
     */
    public static boolean addUser(String username, String password, String firstName, String lastName, String status, String group, String userPermission) {
        boolean successful = false;
        try {
            String sql = "INSERT INTO Permissions (userFirstName, userLastName, username, pword, userStatus, userGroup, permission) VALUES ( ?, ?, ?, ?, ?, ?, ?);";
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            prep.setString(1, firstName);
            prep.setString(2, lastName);
            prep.setString(3, username);
            prep.setString(4, EncryptionHandler.encryptPassword(password));
            prep.setString(5, status);
            prep.setString(6, group);
            prep.setString(7, userPermission);
            prep.execute();
            prep.close();
            successful = true;
            //Log the action
            String message = "SUCCESS: The user \"" + username + "\" was added to the system.";
            iLogger.logMessage(message, "Add", "User");
        } catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException ex) {
            String message = "An error occurred while adding a user to the database.\n"
                    + "This username already exists.";
            logger.log(Level.SEVERE, message, ex);
            successful = false;
            Utilities.showErrorMessage(null, message);
        } catch (Exception e) {
            String message = "An error occurred while adding a user to the database.";
            logger.log(Level.SEVERE, message, e);
            successful = false;
        }
        return successful;
    }

    /**
     * This returns a table model containing a list of all the users.
     * @return
     */
    public static DefaultTableModel getUserList() {
        ArrayList<String> id = new ArrayList<String>();
        ArrayList<String> name = new ArrayList<String>();
        ArrayList<String> username = new ArrayList<String>();
        ArrayList<String> status = new ArrayList<String>();
        try {
            String sql = "SELECT id, (userFirstName +' ' + userLastName) AS name, username, userStatus FROM Permissions ORDER BY id ASC;";
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            ResultSet rs = prep.executeQuery();
            while (rs.next()) {
                id.add(rs.getString("id"));
                name.add(rs.getString("name"));
                username.add(rs.getString("username"));
                status.add(rs.getString("userStatus"));
            }
            rs.close();
            prep.close();
        } catch (SQLException sQLException) {
            String message = "An error occurred while getting the user list.";
            logger.log(Level.SEVERE, message, sQLException);
        }
        DefaultTableModel model = new DefaultTableModel() {

            @Override
            public boolean isCellEditable(int rowIndex, int mColIndex) {
                return false;
            }
        };
        model.addColumn("ID", id.toArray());
        model.addColumn("Name", name.toArray());
        model.addColumn("User Name", username.toArray());
        model.addColumn("Status", status.toArray());
        return model;
    }

    /**
     * This function gets the information for a specific user.
     * @param ID
     * @return
     */
    public static String[] getUserInfo(String ID) {
        String sql = "SELECT * FROM Permissions WHERE id = ?;";
        String userFirstName = "", userLastName = "", username = "", pword = "", userStatus = "", userGroup = "", permission = "";
        try {
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            prep.setString(1, ID);
            ResultSet rs = prep.executeQuery();
            while (rs.next()) {
                userFirstName = rs.getString("userFirstName");//0
                userLastName = rs.getString("userLastName");//1
                username = rs.getString("username");//2
                pword = rs.getString("pword");//3
                userStatus = rs.getString("userStatus");//4
                userGroup = rs.getString("userGroup");//4
                permission = rs.getString("permission");//4
            }
            rs.close();
            prep.close();
        } catch (Exception e) {
            String message = "An error occurred while getting the user list.";
            logger.log(Level.SEVERE, message, e);
        }
        String[] results = {
            userFirstName, userLastName, username, pword, userStatus, userGroup, permission
        };
        return results;
    }

    public static String getUserID(String usrName) {
        String usrID = "";
        try {
            String sql = "SELECT id FROM Permissions WHERE username = ?;";
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            prep.setString(1, usrName);
            ResultSet rs = prep.executeQuery();
            while (rs.next()) {
                usrID = rs.getString("id");
            }
            rs.close();
            prep.close();
        } catch (Exception e) {
            String message = "An error occurred while getting the user ID.";
            logger.log(Level.SEVERE, message, e);
        }
        return usrID;
    }

    /**
     * This method will update the information for a specified user with the values given.
     * @param ID
     * @param firstName
     * @param lastName
     * @param userName
     * @param password
     * @param group
     * @param status
     * @return True of the action was completed successfully.
     *         False if anything went wrong.
     */
    public static boolean updateUser(String ID, String firstName, String lastName, String userName, String password, String status, String group, String permission) {
        boolean successful = false;
        String sql = "UPDATE Permissions SET userFirstName= ?, userLastName= ?, username= ?, pword= ?, userStatus= ?, userGroup = ? , permission = ? WHERE id= ?";
        String[] currentInfo = getUserInfo(ID);
        if (!currentInfo[3].equals(password)) {
            password = EncryptionHandler.encryptPassword(password);
        }
        try {
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            prep.setString(1, firstName);
            prep.setString(2, lastName);
            prep.setString(3, userName);
            prep.setString(4, password);
            prep.setString(5, status);
            prep.setString(6, group);
            prep.setString(7, permission);
            prep.setString(8, ID);
            prep.executeUpdate();
            prep.close();
            successful = true;
            //Log the action
            String message = "SUCCESS: " + userName + "'s information was changed.";
            iLogger.logMessage(message, "Update", "User");
        } catch (Exception e) {
            String message = "An error occurred while updating the user's information.";
            logger.log(Level.SEVERE, message, e);
        }
        return successful;
    }

    /**
     * @return the userName
     */
    public static String getUserName() {
        return userName;
    }

    /**
     * Changes a specified user's password.
     *
     * @param userName
     * @param password
     * @return True if the change operation was successful.
     * */
    public static boolean changePassword(String userUame, String password) {
        boolean successful = false;
        String sql = "UPDATE Permissions SET pword = ?  WHERE username = ?";
        try {
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            prep.setString(1, password);
            prep.setString(2, userName);
            prep.executeUpdate();
            prep.close();
            successful = true;
            //Log the action
            String message = "SUCCESS: " + userName + "'s password was changed.";
            iLogger.logMessage(message, "Update", "User");
        } catch (Exception e) {
            String message = "An error occurred while updating the user's information.";
            logger.log(Level.SEVERE, message, e);
        }
        return successful;
    }

    /**
     * @return the timeout
     */
    public static int getTimeout() {
        return timeout;
    }

    /**
     * 
     * @param currentPath
     * @return 
     */
    public static boolean previligeAvailable(String currentPath) {
        String[] prevList = getPermissions().split("\\|");
        for (String prevItem : prevList) {
            String[] split = prevItem.split("-");
            String item = split[0];
            if (item.equals(currentPath) && (split[1].equalsIgnoreCase("True"))) //if the prevelige matches the row set check the path.
            {
                return true;
            }
        }
        return false;
    }

    public static ArrayList<String> getUserGroups() {
        ArrayList<String> groups = new ArrayList<String>();
        String sql = "SELECT DISTINCT groupName FROM userGroups ORDER BY groupName ASC";
        try {
            PreparedStatement prep = Environment.getDbConn().prepareStatement(sql);
            ResultSet rs = prep.executeQuery();
            while (rs.next()) {
                groups.add(rs.getString("groupName"));
            }
            rs.close();
            prep.close();
        } catch (Exception e) {
            String message = "An error occurred while getting the user group listing.";
            logger.log(Level.SEVERE, message, e);
        }
        return groups;
    }

    /**
     * 
     * @param currentPath
     * @param permissionString
     * @return 
     */
    public static boolean previligeAvailable(String currentPath, String permissionString) {
        String[] prevList = permissionString.split("\\|");
        for (String prevItem : prevList) {
            String[] split = prevItem.split("-");
            String item = split[0];
            if (item.equals(currentPath) && (split[1].equalsIgnoreCase("True"))) //if the prevelige matches the row set check the path.
            {
                return true;
            }
        }
        return false;
    }

    public static String getPermissions() {
        return permissions;
    }
}
